// ----------------------------------
// RSDK Project: Sonic 2
// Script Description: Crawl Object
// Script Author: Christian Whitehead/Simon Thomley
// Unpacked by Rubberduckycooly's script unpacker
// ----------------------------------

// ========================
// Aliases
// ========================

private alias object.value0 : object.timer
private alias object.value1 : object.startPos.x
private alias object.value2 : object.startPos.y
private alias object.value3 : object.foundTarget
private alias object.value4 : object.prevState

// States
private alias 0 : CRAWL_SETUP
private alias 1 : CRAWL_MOVING
private alias 2 : CRAWL_IDLE
private alias 3 : CRAWL_DEFEND

// Player Aliases
private alias object.xpos : player.xpos
private alias object.ypos : player.ypos
private alias object.xvel : player.xvel
private alias object.yvel : player.yvel
private alias object.speed : player.speed
private alias object.gravity : player.gravity
private alias object.animation : player.animation

private alias object.value1  : player.timer
private alias object.value40 : player.hitboxLeft
private alias object.value38 : player.hitboxTop
private alias object.value41 : player.hitboxRight
private alias object.value39 : player.hitboxBottom

// Path ID Aliases
private alias 0 : PATH_A


// ========================
// Function Declarations
// ========================

reserve function Crawl_DebugDraw
reserve function Crawl_DebugSpawn
reserve function Crawl_FindTarget
reserve function Crawl_HandleBump


// ========================
// Function Definitions
// ========================

private function Crawl_DebugDraw
	DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
end function


private function Crawl_DebugSpawn
	CreateTempObject(TypeName[Crawl], 0, object.xpos, object.ypos)
	object[tempObjectPos].startPos.x = object.xpos
	object[tempObjectPos].startPos.y = object.ypos
	object[tempObjectPos].direction = object.direction
end function


private function Crawl_FindTarget
	object.foundTarget = false

	foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
		temp0 = player[currentPlayer].xpos
		temp0 -= object.xpos
		Abs(temp0)
		if temp0 < 0x400000
			temp0 = player[currentPlayer].ypos
			temp0 -= object.ypos
			Abs(temp0)
			if temp0 < 0x400000
				object.foundTarget |= true
			end if
		end if
	next
end function


private function Crawl_HandleBump
	temp0 = player[currentPlayer].xpos
	temp0 -= object.xpos
	temp1 = player[currentPlayer].ypos
	temp1 -= object.ypos
	ATan2(temp2, temp0, temp1)
	Cos256(temp0, temp2)
	Sin256(temp1, temp2)
	temp0 *= 0x700
	temp1 *= 0x700
	player[currentPlayer].timer	= 0
	player[currentPlayer].speed	= temp0
	player[currentPlayer].xvel 	= temp0
	player[currentPlayer].yvel 	= temp1
	PlaySfx(SfxName[Bumper], false)
end function


// ========================
// Events
// ========================

event ObjectUpdate
	switch object.state
	case CRAWL_SETUP
		if object.priority != PRIORITY_XBOUNDS_DESTROY
			object.priority = PRIORITY_ACTIVE
		end if

		if object.direction == FLIP_NONE
			object.xvel = -0x2000
		else
			object.xvel = 0x2000
		end if

		object.state = CRAWL_MOVING
		break

	case CRAWL_MOVING
		object.xpos += object.xvel
		ObjectTileGrip(CSIDE_FLOOR, 0, 16, PATH_A)

		object.timer++
		if object.timer == 512
			object.timer = 0
			object.state = CRAWL_IDLE
		end if

		CallFunction(Crawl_FindTarget)
		if object.foundTarget == true
			object.prevState = object.state
			object.state = CRAWL_DEFEND
			object.frame = 0
			object.animationTimer = 0
		end if

		object.frame = object.animationTimer
		object.frame /= 20
		object.animationTimer++
		object.animationTimer %= 40
		break

	case CRAWL_IDLE
		object.timer++
		if object.timer == 60
			object.timer = 0
			object.direction ^= FLIP_X
			FlipSign(object.xvel)
			object.state = CRAWL_MOVING
		end if

		CallFunction(Crawl_FindTarget)
		if object.foundTarget == true
			object.prevState = object.state
			object.state = CRAWL_DEFEND
		end if

		object.frame = 0
		object.animationTimer = 0
		break

	case CRAWL_DEFEND
		CallFunction(Crawl_FindTarget)

		if object.foundTarget == false
			object.state = object.prevState
		end if

		object.animationTimer = 0
		break
		
	end switch

	if object.outOfBounds == true
		temp0 = object.xpos
		temp1 = object.ypos
		object.xpos = object.startPos.x
		object.ypos = object.startPos.y
		if object.outOfBounds == true
			if object.priority != PRIORITY_XBOUNDS_DESTROY
				object.priority = PRIORITY_BOUNDS
			end if
			object.state = CRAWL_SETUP
		else
			object.xpos = temp0
			object.ypos = temp1
		end if
	end if

	foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
		BoxCollisionTest(C_TOUCH, object.entityPos, -15, -16, 15, 16, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
		if checkResult == true
			if player[currentPlayer].animation == ANI_JUMPING
				if player[currentPlayer].gravity == GRAVITY_AIR
					CallFunction(Crawl_HandleBump)
					object.frame = 3
				else
					if object.direction == FLIP_NONE
						if player[currentPlayer].xpos > object.xpos
							CallFunction(Player_BadnikBreak)
						else
							CallFunction(Crawl_HandleBump)
							object.frame = 2
						end if
					else
						if player[currentPlayer].xpos < object.xpos
							CallFunction(Player_BadnikBreak)
						else
							CallFunction(Crawl_HandleBump)
							object.frame = 2
						end if
					end if
				end if
			else
				CallFunction(Player_BadnikBreak)
			end if
		end if
	next
end event


event ObjectDraw
	DrawSpriteFX(object.frame, FX_FLIP, object.xpos, object.ypos)
end event


event ObjectStartup
	CheckCurrentStageFolder("Zone04")
	if checkResult == False
		LoadSpriteSheet("CNZ/Objects.gif")
		SpriteFrame(-23, -16, 47, 32, 1, 1)
		SpriteFrame(-31, -16, 59, 32, 49, 1)
		SpriteFrame(-24, -16, 40, 32, 109, 1)
		SpriteFrame(-32, -16, 48, 32, 150, 1)
	else
		LoadSpriteSheet("MBZ/Objects.gif")
		SpriteFrame(-23, -16, 47, 32, 436, 256)
		SpriteFrame(-31, -16, 59, 32, 484, 256)
		SpriteFrame(-24, -16, 40, 32, 544, 256)
		SpriteFrame(-32, -16, 48, 32, 585, 256)
	end if

	foreach (TypeName[Crawl], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].startPos.x = object[arrayPos0].xpos
		object[arrayPos0].startPos.y = object[arrayPos0].ypos
	next

	SetTableValue(TypeName[Crawl], DebugMode_ObjCount, DebugMode_TypesTable)
	SetTableValue(Crawl_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
	SetTableValue(Crawl_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
	DebugMode_ObjCount++
end event


// ========================
// Editor Events
// ========================

event RSDKDraw
	DrawSprite(0)
end event


event RSDKLoad
	CheckCurrentStageFolder("Zone04")
	if checkResult == true
		LoadSpriteSheet("CNZ/Objects.gif")
		SpriteFrame(-23, -16, 47, 32, 1, 1)
	else
		LoadSpriteSheet("MBZ/Objects.gif")
		SpriteFrame(-23, -16, 47, 32, 436, 256)
	end if
	
	// Set to 172 in the scene for some reason?
	// dunno what that's about, but at the very least i can say that this value isn't used here
	SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
end event
